#include<iostream>
#include<thread>
#include<list>
#include<vector>
#include<mutex>

using namespace std;

class A {
    public:
    void inMsgRecvQueue(){
        for(int i=0;i<1000;i++)
        {
            cout<<"插入元素"<<endl;

        //    my_mutex.lock();  //只保护共享数据
        //     msgRecvQueue.emplace_back(i);
        //     my_mutex.unlock(); 

        lock_guard<mutex> sbfuard(my_mutex);
        msgRecvQueue.emplace_back(i);

        }
    }
    void outMsgRecvQueue(){
        for(int i=0;i<1000;i++){
            my_mutex.lock();
            if(!msgRecvQueue.empty()){
                int command = msgRecvQueue.front();
                msgRecvQueue.pop_back();
            }else{
                cout<<"消息队列为空"<<endl;
            }
            my_mutex.unlock();
        }
        cout<<"end"<<endl;
    }
    private:
    list<int> msgRecvQueue;
    mutex my_mutex;
};

//不允许调用多次unlock，或者lock

//有lock()，忘记unlock的问题，非常难排查
//为防止unlock，引入一个lock_guard的类。使用了lock——guard之后，就不能使用lock，unlock
//lock_guard的构造函数是lock() ,析构是unlock()
//如果想限定锁定区域，使用{}
  
//死锁
//一个互斥量，一把锁
//解决方案：
//只要两把锁，上所顺序一致就可以

//std::lock()函数模板
//一次能锁两个或者以上的互斥量
//如果互斥量中有一个没有锁住，他就会等在那里，等所有互斥量都锁住
//要么连个互斥量都锁住，要么两个都没有锁住

//lock之后，使用lock_guard完成自动解锁
//lock(mutext)
//lock_guard<mutex> sblock_guard(mutext, adopt_lock);

//unique_lock取代lock_guard
//unique_lock是个类模板，工作中，一般lock_guard()
//unique_lcok更加灵活
//mymutex.lock()
//unique_lock<mutex> sbgurad(mymutex, adopt_lock )
//try_to_lock()会尝试取锁定这个mutex，但如果没有锁定成功，我也会立即返回，并不会阻塞在那里
//不能两次上所，不然，容易导致程序卡死
//defer_lock
//使用defer_lock的话，不能自己先lock，否则会报异常
//初始化一个没有lock的mutex
//unique_lock的成员函数
//lock()加锁
//unlock()解锁
//try_lock()尝试给互斥量加锁，如果拿不到锁，就会返回false，函数不会阻塞
//release(), 返回他所管理的mutex对象指针，并释放所有权；也就说这个unique_lock和mutex不再有关系
//如果这时mutex上锁了，这时就需要手动解锁 


void test01(){
    mutex my_mutex;
    unique_lock<mutex> sbguard(my_mutex,try_to_lock);
    if(sbguard.owns_lock()){
        cout<<"拿到锁了，操作共享数据";
    }else{
        cout<<"没有拿到锁，干点别的事情"<<endl;
    }
}

void test02(){
    mutex my_mutex;
    unique_lock<mutex> sbguard(my_mutex,defer_lock);
    sbguard.lock(); //不需要自己解锁
    //处理共享数据
    sbguard.unlock();
    //处理非共享数据
    sbguard.lock();
}

void test03(){
    mutex my_mutex;
    unique_lock<mutex> sbguard(my_mutex,defer_lock);
    if(sbguard.try_lock()){
        //处理共享数据
    }
}

//一个mutex需要和一个unique_lock()
//unique_lock()的所有权只能转移，不能复制  unique_lock(move(sbguard))
//对同一个mutex量，进行两次unique_lock()就会报错  如果使用lock_gard的话，编译通过，但是，运行可能会卡死
//所有权转移方法：move；return unique


int main(){
    thread myobj(myprint);  
    myobj.join();  

    cout<<"i love china"<<endl; 

    return 0;
}
